// Copyright (c) 2012 Rene Bolldorf <rb@radix.io>
// Use of this source is governed by the GNU General Public License version 3,
// the license can be found in the LICENSE file.

doa.prototype.requestDelegate = function (realm, userId, dragonHeart) {
  this._realm = realm;
  this._defaultParams = 'user%5Fid=' + userId + '&dragon%5Fheart=' +
                        dragonHeart + '&%5Fsession%5Fid=&version=saturnv';
  this._cache = {};
};

doa.prototype.requestDelegate.prototype._constructURL = function (endpoint) {
  return 'http://' + this._realm + '.castle.wonderhill.com/api/' + endpoint;
};

doa.prototype.requestDelegate.prototype._hash = function (url, params) {
  return hex_sha1('Draoumculiasis' + params + 'LandCrocodile' + url + 'Bevar-Asp');
};

doa.prototype.requestDelegate.prototype._checkIfErr = function (obj) {
  var self = this;
  var req_err = obj['errors'];
  if (req_err) {
    return 'unknown error';
  } else {
    var res = obj['result'];
    if (res) {
      if (!res['success']) {
        return res['errors'][0];
      }
    }
  }
  return null;
};

doa.prototype.requestDelegate.prototype._needRefresh = function (str) {
  if (this._cache[str] != null)
    var lastRefresh = this._cache[str][0];
  else
    var lastRefresh = 0;

  var now = new Date().getTime();

  if ((now - lastRefresh) / 1000 > 60)
    return true;
  else
    return false;
};

doa.prototype.requestDelegate.prototype._post = function (endpoint, params, callback) {
  var url = this._constructURL(endpoint);
  var _params = this._defaultParams + '&timestamp=' + new Date().getTime();
  if (params) {
    _params += params;
  }
  var xhr = new XMLHttpRequest();
  var self = this;
  xhr.onloadend = function () {
    if (xhr.status == 200) {
      callback(JSON.parse(xhr.responseText));
    } else {
      callback(null, '_post error, status: ' + xhr.status);
    }
  };
  xhr.open("POST", url);
  xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
  xhr.setRequestHeader('X-S3-AWS', this._hash(url, _params));
  xhr.send(_params);
};

doa.prototype.requestDelegate.prototype._get = function (endpoint, params, callback) {
  var url = this._constructURL(endpoint) + '?'
            + this._defaultParams + '&timestamp='
            + new Date().getTime();

  if (params)
    url += params;

  var xhr = new XMLHttpRequest();
  var self = this;
  xhr.onloadend = function () {
    if (xhr.status == 200) {
      callback(JSON.parse(xhr.responseText));
    } else {
      callback(null, '_get error, status: ' + xhr.status);
    }
  };
  xhr.open('GET', url);
  xhr.send();
};

doa.prototype.requestDelegate.prototype.player = function (no_cache, callback) {
  if (this._needRefresh('player') || no_cache) {
    var self = this;
    this._get('player.json', null, function (obj, err) {
      if (err)
        callback(null, err);
      else {
        var api_err = self._checkIfErr(obj);
        if (!api_err) {
          self._cache['player'] = [ new Date().getTime(), obj ];
          callback(obj);
        } else
          callback(null, api_err);
      }
  });
  } else {
    callback(this._cache['player'][1]);
  }
};

doa.prototype.requestDelegate.prototype.generals = function (no_cache,
  capital_id, callback) {

  var self = this;

  if (this._needRefresh('generals') || no_cache) {
    this._get('cities/' + capital_id + '/generals.json', null,
      function (obj, err) {
        if (err)
          callback(null, err);
        else {
          var api_err = self._checkIfErr(obj);
          if (!api_err) {
            self._cache['generals'] = [ new Date().getTime(), obj ];
            callback(obj);
          } else
            callback(null, api_err);
        }
    });
  } else {
    callback(this._cache['generals'][1]);
  }
};

doa.prototype.requestDelegate.prototype.jobs = function (no_cache, callback) {
  if (this._needRefresh('jobs') || no_cache) {
    var self = this;
    this._get('player/jobs.json', null, function (obj, err) {
      if (err)
        callback(null, err);
      else {
        var api_err = self._checkIfErr(obj);
        if (!api_err) {
          self._cache['jobs'] = [ new Date().getTime(), obj ];
          callback(obj, null);
        } else
          callback(null, api_err);
     }
  });
  } else {
    callback(this._cache['jobs'][1]);
  }
};

doa.prototype.requestDelegate.prototype.city = function (no_cache, city_id,
  callback) {

  if (this._needRefresh(city_id) || no_cache) {
    var self = this;
    this._post('cities/' + city_id + '.json', null, function (obj, err) {
      if(err)
        callback(null, err);
      else {
        var api_err = self._checkIfErr(obj);
        if (!api_err) {
          self._cache[city_id] = [ new Date().getTime(), obj ];
          callback(obj, null);
        } else
          callback(null, api_err);
      }
    });
  } else
    callback(this._cache[city_id][1]);
};

doa.prototype.requestDelegate.prototype.attack = function (x, y, general,
  troops, capital_id, callback) {
  var self = this;

  var params = { 'march[x]' : x,
                 'march[y]' : y,
                 'march[march_type]' : 'attack',
                 'march[general_id]': general
  };
  var v = ''
  for (k in params) {
    v += '&' + k + '=' + params[k];
  }
  var esc_params = window.encodeURI(v + '&' + 'march[units]=' + JSON.stringify(troops));

  this._post('cities/' + capital_id + '/marches.json', esc_params,
    function (obj, err) {
      if (err)
        callback(null, err);
      else {
        var api_err = self._checkIfErr(obj);
        if (!api_err)
          callback(obj);
        else
          callback(null, api_err);
      }
  });
};

doa.prototype.requestDelegate.prototype.collect = function (id, callback) {
  var self = this;

  this._post('cities/' + id + '/move_resources.json', null,
    function (obj, err) {
      if (err)
        callback(err);
      else {
        var api_err = self._checkIfErr(obj);
        if (!api_err)
          callback(null);
        else
          callback(api_err);
      }
  });
};

doa.prototype.requestDelegate.prototype.upgrade = function (city_id, building_id, callback) {
  var self = this;

  this._post('cities/' + city_id + '/buildings/' + building_id + '.json',
    '&_method=put', function (obj, err) {
      if (err)
        callback(err);
      else {
        var api_err = self._checkIfErr(obj);
        if (!api_err)
          callback(null);
        else
          callback(api_err);
      }
  });
};
